package com.lh.feign;

import com.lh.AbstractLogPostProcessor;
import feign.Client;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeansException;
import org.springframework.cloud.netflix.ribbon.SpringClientFactory;
import org.springframework.cloud.openfeign.ribbon.CachingSpringLoadBalancerFactory;
import org.springframework.cloud.openfeign.ribbon.LoadBalancerFeignClient;

import java.lang.reflect.Field;
import java.util.List;

/**
 * @author: linghao
 * @since: 2022/10/26
 */
@Slf4j
public class FeignClientPostProcessor extends AbstractLogPostProcessor {

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        if(bean instanceof Client){
            List<FeignClientInterceptor> feignClientInterceptorList = this.getBeanOfType(FeignClientInterceptor.class);
            if(feignClientInterceptorList != null && feignClientInterceptorList.size() != 0){
                if(bean instanceof LoadBalancerFeignClient){
                    Client delegate = ((LoadBalancerFeignClient) bean).getDelegate();
                    FeignClient feignClient = new FeignClient(delegate, feignClientInterceptorList);
                    try {
                        Field field = LoadBalancerFeignClient.class.getDeclaredField("lbClientFactory");
                        field.setAccessible(true);
                        CachingSpringLoadBalancerFactory loadBalancerFactory = (CachingSpringLoadBalancerFactory)field.get(bean);
                        field = LoadBalancerFeignClient.class.getDeclaredField("clientFactory");
                        field.setAccessible(true);
                        SpringClientFactory clientFactory = (SpringClientFactory)field.get(bean);
                        return new LoadBalancerFeignClient(delegate,loadBalancerFactory,clientFactory);
                    }catch (Exception e){
                        log.error(e.getMessage());
                        return bean;
                    }
                }else{

                }
            }else{
                return bean;
            }
        }else{
            return bean;
        }
        return bean;
    }
}
